<!DOCTYPE HTML>
<html lang="zh-CN">


<head>
    <meta charset="utf-8">
    <meta name="keywords" content="自监督学习Self-Supervised Learning, J Sir">
    <meta name="description" content="">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <meta name="renderer" content="webkit|ie-stand|ie-comp">
    <meta name="mobile-web-app-capable" content="yes">
    <meta name="format-detection" content="telephone=no">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
    <!-- Global site tag (gtag.js) - Google Analytics -->


    <title>自监督学习Self-Supervised Learning | J Sir</title>
    <link rel="icon" type="image/png" href="/favicon.png">

    <link rel="stylesheet" type="text/css" href="/libs/awesome/css/all.css">
    <link rel="stylesheet" type="text/css" href="/libs/materialize/materialize.min.css">
    <link rel="stylesheet" type="text/css" href="/libs/aos/aos.css">
    <link rel="stylesheet" type="text/css" href="/libs/animate/animate.min.css">
    <link rel="stylesheet" type="text/css" href="/libs/lightGallery/css/lightgallery.min.css">
    <link rel="stylesheet" type="text/css" href="/css/matery.css">
    <link rel="stylesheet" type="text/css" href="/css/my.css">

    <script src="/libs/jquery/jquery.min.js"></script>

<meta name="generator" content="Hexo 6.0.0">
<style>.github-emoji { position: relative; display: inline-block; width: 1.2em; min-height: 1.2em; overflow: hidden; vertical-align: top; color: transparent; }  .github-emoji > span { position: relative; z-index: 10; }  .github-emoji img, .github-emoji .fancybox { margin: 0 !important; padding: 0 !important; border: none !important; outline: none !important; text-decoration: none !important; user-select: none !important; cursor: auto !important; }  .github-emoji img { height: 1.2em !important; width: 1.2em !important; position: absolute !important; left: 50% !important; top: 50% !important; transform: translate(-50%, -50%) !important; user-select: none !important; cursor: auto !important; } .github-emoji-fallback { color: inherit; } .github-emoji-fallback img { opacity: 0 !important; }</style>
</head>




<body>
    <header class="navbar-fixed">
    <nav id="headNav" class="bg-color nav-transparent">
        <div id="navContainer" class="nav-wrapper container">
            <div class="brand-logo">
                <a href="/" class="waves-effect waves-light">
                    
                    <img src="/medias/logo.png" class="logo-img" alt="LOGO">
                    
                    <span class="logo-span">J Sir</span>
                </a>
            </div>
            

<a href="#" data-target="mobile-nav" class="sidenav-trigger button-collapse"><i class="fas fa-bars"></i></a>
<ul class="right nav-menu">
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/" class="waves-effect waves-light">
      
      <i class="fas fa-home" style="zoom: 0.6;"></i>
      
      <span>首页</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/tags" class="waves-effect waves-light">
      
      <i class="fas fa-tags" style="zoom: 0.6;"></i>
      
      <span>标签</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/categories" class="waves-effect waves-light">
      
      <i class="fas fa-bookmark" style="zoom: 0.6;"></i>
      
      <span>分类</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/archives" class="waves-effect waves-light">
      
      <i class="fas fa-archive" style="zoom: 0.6;"></i>
      
      <span>归档</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/about" class="waves-effect waves-light">
      
      <i class="fas fa-user-circle" style="zoom: 0.6;"></i>
      
      <span>关于</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/contact" class="waves-effect waves-light">
      
      <i class="fas fa-comments" style="zoom: 0.6;"></i>
      
      <span>留言板</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/friends" class="waves-effect waves-light">
      
      <i class="fas fa-address-book" style="zoom: 0.6;"></i>
      
      <span>友情链接</span>
    </a>
    
  </li>
  
  <li>
    <a href="#searchModal" class="modal-trigger waves-effect waves-light">
      <i id="searchIcon" class="fas fa-search" title="搜索" style="zoom: 0.85;"></i>
    </a>
  </li>
</ul>


<div id="mobile-nav" class="side-nav sidenav">

    <div class="mobile-head bg-color">
        
        <img src="/medias/logo.png" class="logo-img circle responsive-img">
        
        <div class="logo-name">J Sir</div>
        <div class="logo-desc">
            
            Never really desperate, only the lost of the soul.
            
        </div>
    </div>

    

    <ul class="menu-list mobile-menu-list">
        
        <li class="m-nav-item">
	  
		<a href="/" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-home"></i>
			
			首页
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/tags" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-tags"></i>
			
			标签
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/categories" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-bookmark"></i>
			
			分类
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/archives" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-archive"></i>
			
			归档
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/about" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-user-circle"></i>
			
			关于
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/contact" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-comments"></i>
			
			留言板
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/friends" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-address-book"></i>
			
			友情链接
		</a>
          
        </li>
        
        
        <li><div class="divider"></div></li>
        <li>
            <a href="https://github.com/jy741" class="waves-effect waves-light" target="_blank">
                <i class="fab fa-github-square fa-fw"></i>Fork Me
            </a>
        </li>
        
    </ul>
</div>


        </div>

        
            <style>
    .nav-transparent .github-corner {
        display: none !important;
    }

    .github-corner {
        position: absolute;
        z-index: 10;
        top: 0;
        right: 0;
        border: 0;
        transform: scale(1.1);
    }

    .github-corner svg {
        color: #0f9d58;
        fill: #fff;
        height: 64px;
        width: 64px;
    }

    .github-corner:hover .octo-arm {
        animation: a 0.56s ease-in-out;
    }

    .github-corner .octo-arm {
        animation: none;
    }

    @keyframes a {
        0%,
        to {
            transform: rotate(0);
        }
        20%,
        60% {
            transform: rotate(-25deg);
        }
        40%,
        80% {
            transform: rotate(10deg);
        }
    }
</style>

<a href="https://github.com/jy741" class="github-corner tooltipped hide-on-med-and-down" target="_blank"
   data-tooltip="Fork Me" data-position="left" data-delay="50">
    <svg viewBox="0 0 250 250" aria-hidden="true">
        <path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path>
        <path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2"
              fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path>
        <path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z"
              fill="currentColor" class="octo-body"></path>
    </svg>
</a>
        
    </nav>

</header>

    



<div class="bg-cover pd-header post-cover" style="background-image: url('/medias/featureimages/1.jpg')">
    <div class="container" style="right: 0px;left: 0px;">
        <div class="row">
            <div class="col s12 m12 l12">
                <div class="brand">
                    <h1 class="description center-align post-title">自监督学习Self-Supervised Learning</h1>
                </div>
            </div>
        </div>
    </div>
</div>




<main class="post-container content">

    
    <link rel="stylesheet" href="/libs/tocbot/tocbot.css">
<style>
    #articleContent h1::before,
    #articleContent h2::before,
    #articleContent h3::before,
    #articleContent h4::before,
    #articleContent h5::before,
    #articleContent h6::before {
        display: block;
        content: " ";
        height: 100px;
        margin-top: -100px;
        visibility: hidden;
    }

    #articleContent :focus {
        outline: none;
    }

    .toc-fixed {
        position: fixed;
        top: 64px;
    }

    .toc-widget {
        width: 345px;
        padding-left: 20px;
    }

    .toc-widget .toc-title {
        padding: 35px 0 15px 17px;
        font-size: 1.5rem;
        font-weight: bold;
        line-height: 1.5rem;
    }

    .toc-widget ol {
        padding: 0;
        list-style: none;
    }

    #toc-content {
        padding-bottom: 30px;
        overflow: auto;
    }

    #toc-content ol {
        padding-left: 10px;
    }

    #toc-content ol li {
        padding-left: 10px;
    }

    #toc-content .toc-link:hover {
        color: #42b983;
        font-weight: 700;
        text-decoration: underline;
    }

    #toc-content .toc-link::before {
        background-color: transparent;
        max-height: 25px;

        position: absolute;
        right: 23.5vw;
        display: block;
    }

    #toc-content .is-active-link {
        color: #42b983;
    }

    #floating-toc-btn {
        position: fixed;
        right: 15px;
        bottom: 76px;
        padding-top: 15px;
        margin-bottom: 0;
        z-index: 998;
    }

    #floating-toc-btn .btn-floating {
        width: 48px;
        height: 48px;
    }

    #floating-toc-btn .btn-floating i {
        line-height: 48px;
        font-size: 1.4rem;
    }
</style>
<div class="row">
    <div id="main-content" class="col s12 m12 l9">
        <!-- 文章内容详情 -->
<div id="artDetail">
    <div class="card">
        <div class="card-content article-info">
            <div class="row tag-cate">
                <div class="col s7">
                    
                    <div class="article-tag">
                        
                            <a href="/tags/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/">
                                <span class="chip bg-color">机器学习</span>
                            </a>
                        
                            <a href="/tags/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/">
                                <span class="chip bg-color">深度学习</span>
                            </a>
                        
                    </div>
                    
                </div>
                <div class="col s5 right-align">
                    
                </div>
            </div>

            <div class="post-info">
                
                <div class="post-date info-break-policy">
                    <i class="far fa-calendar-minus fa-fw"></i>发布日期:&nbsp;&nbsp;
                    2022-12-10
                </div>
                

                

                
                <div class="info-break-policy">
                    <i class="far fa-file-word fa-fw"></i>文章字数:&nbsp;&nbsp;
                    5.4k
                </div>
                

                

                
                    <div id="busuanzi_container_page_pv" class="info-break-policy">
                        <i class="far fa-eye fa-fw"></i>阅读次数:&nbsp;&nbsp;
                        <span id="busuanzi_value_page_pv"></span>
                    </div>
				
            </div>
        </div>
        <hr class="clearfix">

        
        <!-- 是否加载使用自带的 prismjs. -->
        <link rel="stylesheet" href="/libs/prism/prism.css">
        

        

        <div class="card-content article-card-content">
            <div id="articleContent">
                <h1 id="奶茶鼠的想法"><a href="#奶茶鼠的想法" class="headerlink" title="奶茶鼠的想法"></a>奶茶鼠的想法</h1><p><img src="https://pluto-1300780100.cos.ap-nanjing.myqcloud.com/img/de00742f63e21923c1123bb3f734f2f5aec523ad.png@1036w.webp" alt="img" style="zoom:33%;"></p>
<span id="more"></span>
<h1 id="Self-Supervised-Learning"><a href="#Self-Supervised-Learning" class="headerlink" title="Self-Supervised Learning"></a>Self-Supervised Learning</h1><p>Self-Supervised Learning，又称为自监督学习，我们知道一般机器学习分为有监督学习，无监督学习和强化学习。 而 Self-Supervised Learning 是无监督学习里面的一种，主要是希望能够学习到一种通用的特征表达用于下游任务 (Downstream Tasks)。 其主要的方式就是通过自己监督自己。</p>
<p>Yann Lecun 曾在一个关于 Self-supervised learning 的演讲中讲到：Self-supervised learning 是 The dark matter of intelligence，意为 智能的暗物质。他说：</p>
<blockquote>
<p>Self-supervised learning enables AI systems to learn from orders of magnitude more data, which is important to recognize and understand patterns of more subtle, less common representations of the world. (自监督学习使人工智能系统能够从更大数量级的数据中学习，这对于识别和理解更微妙、更不常见的世界表示模式很重要。)</p>
</blockquote>
<p><strong>Self-Supervised Learning 的核心思想</strong>：在预训练阶段我们使用无标签的数据集 (unlabeled data)，因为有标签的数据集很贵，打标签得要多少人工劳力去标注，那成本是相当高的，所以这玩意太贵。相反，无标签的数据集网上随便到处爬，它便宜。在训练模型参数的时候，我们不追求把这个参数用带标签数据从初始化的一张白纸给一步训练到位，原因就是数据集太贵。于是Self-Supervised Learning就想先把参数从一张白纸训练到初步成型，再从初步成型训练到完全成型。注意这是2个阶段。这个训练到初步成型的东西，我们把它叫做Visual Representation。预训练模型的时候，就是模型参数从一张白纸到初步成型的这个过程，还是用无标签数据集。等我把模型参数训练个八九不离十，这时候再根据你下游任务 (Downstream Tasks)的不同去用带标签的数据集把参数训练到完全成型，那这时用的数据集量就不用太多了，因为参数经过了第1阶段就已经训练得差不多了。</p>
<p>Self-Supervised Learning 不仅是在NLP领域，在CV, 语音领域也有很多经典的工作。它可以分成3类：Data Centric, Prediction (也叫 Generative) Constractive。</p>
<p><img src="https://pluto-1300780100.cos.ap-nanjing.myqcloud.com/img/v2-ab774350b8759d31746430388fc42e2e_720w.webp" alt="img"></p>
<p>我们之前在做 Supervised Learning的时候，如何让model输出我们想要的 y 呢？你得要有label的资料。假设今天要做情感分析，让机器看一段文字，输出对应的情感是正面的还是负面的。那你要有一大堆文章和对应的label，才能够训练model。</p>
<p>那 Self-Supervised 就是在没有label的情况下自己想办法监督自己。还是同样的一堆资料 x ，我们现在把它分成2部分： x′ 和 x″ 。然后把 x′ 输入到模型里面，让它输出 y ，然后我们让 y 与 x″ 越接近越好，这个就是 Self-Supervised Learning。换言之在 Self-Supervised Learning里面输入的一部分作为了监督信号，一部分仍作为输入。</p>
<p><img src="https://pluto-1300780100.cos.ap-nanjing.myqcloud.com/img/image-20221207211301102.png" alt="image-20221207211301102"></p>
<h1 id="BERT"><a href="#BERT" class="headerlink" title="BERT"></a>BERT</h1><p>那么如何把输入的 x 分成2部分： x′ 和 x″ 呢？这就要用到BERT模型。介绍Bert之前不得不介绍一下芝麻街，Self-Supervised Learning的模型都是以芝麻街的人物来命名的。</p>
<p>ELMo代表的是红色怪物，是Embedding from Language Models的缩写，它是最早的 Self-Supervised Learning的模型。后来又有了BERT (Bidirectional Encoder Representations from Transformers)，是我们最耳熟能详的的 Self-Supervised Learning model。然后BERT最好的朋友是ERNIE (Enhanced Representation through Knowledge Integration)，是紧接着BERT出现的模型。后来又出现了一个叫做大鸟 (Big Bird: Transformers for Longer Sequences) 的模型。</p>
<p><img src="https://pluto-1300780100.cos.ap-nanjing.myqcloud.com/img/image-20221211152901162.png" alt="image-20221211152901162" style="zoom:80%;"></p>
<h2 id="Masking-Input"><a href="#Masking-Input" class="headerlink" title="Masking Input"></a>Masking Input</h2><p>BERT模型，它的架构就是Transformer 的 Encoder，里面有很多Self-attention，Residual connection，Normalization等等。</p>
<p>BERT可以做的事情也就是Transformer 的 Encoder 可以做的事情，就是输入一排向量，输出另外一排向量，输入和输出的维度是一致的。那么不仅仅是一句话可以看做是一个sequence，一段语音也可以看做是一个sequence，甚至一个image也可以看做是一个sequence。所以BERT其实不仅可以用在NLP上，还可以用在CV里面。</p>
<p>接下来要做的事情是把这段输入文字里面的一部分随机盖住。随机盖住有2种，一种是直接用一个Mask把要盖住的token (对中文来说就是一个字)给Mask掉，具体是换成一个特殊的字符。另一种做法是把这个token替换成一个随机的token。</p>
<p><img src="https://pluto-1300780100.cos.ap-nanjing.myqcloud.com/img/image-20221211142726967.png" alt="image-20221211142726967" style="zoom:80%;"></p>
<p>两种方法都可以使用，使用哪种方法也是随机决定的。因此，当BERT进行训练时，向BERT输入一个句子，先随机决定哪一部分的汉字将被mask。</p>
<p>接下来把这个盖住的token对应位置输出的向量做一个Linear Transformation（所谓的Linear transform是指，输入向量将与一个矩阵相乘，然后做softmax，输出一个分布。），再做softmax输出一个分布，这个分布是每一个字的概率。</p>
<p>在训练过程中。我们知道被mask的字符是什么，而BERT不知道，我们可以用一个one-hot vector来表示这个字符，并使输出和one-hot vector之间的交叉熵损失最小。</p>
<p><img src="https://pluto-1300780100.cos.ap-nanjing.myqcloud.com/img/image-20221211142951365.png" alt="image-20221211142951365" style="zoom:80%;"></p>
<h2 id="Next-Sentence-Prediction"><a href="#Next-Sentence-Prediction" class="headerlink" title="Next Sentence Prediction"></a>Next Sentence Prediction</h2><p>事实上，当我们训练BERT时，除了mask之外，我们还会使用另一种方法，这种额外的方法叫做Next Sentence Prediction 。</p>
<p>那我们会先爬取很多的sentence，然后随机地找两个sentence，给他俩中间加上一个分隔符号 <strong>[SEP]</strong>，代表前后是2个不同的句子；然后在最前面加上1个分类符号 <strong>[CLS]</strong>。把这些拼在一起以后输入到BERT里面，当然输出也会是一个Sequence，但是我们只看 <strong>[CLS]</strong> 的输出，并把这个输出通过一个 Linear Transformation，得到二元的分类 “Yes/No”。在这里它代表的意义是：”Sentence 1 和Sentence 2 是不是相接的？”如下图所示。</p>
<p><img src="https://pluto-1300780100.cos.ap-nanjing.myqcloud.com/img/image-20221211143238015.png" alt="image-20221211143238015" style="zoom:67%;"></p>
<p>但是后续有文章，比如<a target="_blank" rel="noopener" href="https://arxiv.org/abs/1907.11692">Robustly optimized BERT approach</a> (RoBERTa) 就说明Next Sentence Prediction是对训练没有什么特别的帮助的，一种可能的原因是判断前后两个句子是不是相接的这个任务太简单了，要知道两个句子是不是应该接在一起也许不是一个特别难的任务。所以BERT可能没有借助Next Sentence Prediction这个任务学到太多的有用的东西。后续的 <a target="_blank" rel="noopener" href="https://arxiv.org/abs/1909.11942">ALBERT</a>中又提出了sentence order prediction的办法，被认为是有作用的，就是判断连续的两个sentence的先后顺序。</p>
<h2 id="Downstream-Tasks"><a href="#Downstream-Tasks" class="headerlink" title="Downstream Tasks"></a>Downstream Tasks</h2><p>我们现在训练的BERT模型其实只会做2件事情：</p>
<ul>
<li>Masked token prediction：预测盖住的词是什么。</li>
<li>Next sentence prediction：预测两个句子是不是前后接起来的。</li>
</ul>
<p>那么接下来神奇的地方是：BERT可以被用在很多<strong>下游任务 (Downstream Tasks)</strong> 上，这些下游任务可能和Masked token prediction，Next sentence prediction毫无关联，但是BERT可以作为预训练模型被用在它们上面。</p>
<p>BERT分化成各种任务的功能细胞，被称为<strong>Fine-tune</strong>(微调)。所以，我们经常听到有人说，他对BERT进行了微调，也就是说他手上有一个BERT，他对这个BERT进行了微调，使它能够完成某种任务，与微调相反，在微调之前产生这个BERT的过程称为预训练。</p>
<p>BERT就像一个胚胎干细胞，它要分化成各种任务的功能细胞，我们通常不会只在一个任务上测试它的能力，你会让这个BERT分化成各种任务的功能细胞，看看它在每个任务上的准确性，然后我们取其平均值，得到一个总分。这种不同任务的集合，，我们可以称之为任务集。任务集中最著名的基准被称为GLUE，它是General Language Understanding Evaluation的缩写。</p>
<p><img src="https://pluto-1300780100.cos.ap-nanjing.myqcloud.com/img/image-20221211143656174.png" alt="image-20221211143656174" style="zoom:80%;"></p>
<p>下图代表的是近年来的模型的GLUE得分，黑色的线代表的是人类的得分，最新的XLNet就在这个任务上超越了人类水平，说明GLUE 这个任务已经被玩坏了，所以后续有了更难的自然语言任务：SuperGLUE让机器来解。</p>
<p><img src="https://pluto-1300780100.cos.ap-nanjing.myqcloud.com/img/image-20221211143800767.png" alt="image-20221211143800767" style="zoom:80%;"></p>
<h2 id="How-to-use-BERT"><a href="#How-to-use-BERT" class="headerlink" title="How to use BERT"></a>How to use BERT</h2><p><strong>Case1：情感分析：输入一个句子，输出对应的情感类别。</strong></p>
<p>BERT是怎么解Sentiment Analysis的问题呢？给它一个句子，CLS标记放在这个句子的前面扔到BERT中。然后，我们只看CLS的部分。CLS在这里输出一个向量，我们对它进行Linear transform，也就是将它乘以一个Linear transform的矩阵，这里省略了Softmax。</p>
<p><img src="https://pluto-1300780100.cos.ap-nanjing.myqcloud.com/img/image-20221211144150946.png" alt="image-20221211144150946" style="zoom:80%;"></p>
<p>值得注意的是，对于这种下游任务你需要有labelled data，也就是说BERT其实没办法凭空解Sentiment Analysis的问题，也是需要一部分有监督数据的。我们此时的情感分析模型包括BERT部分和Linear Transformation部分，只是BERT部分的初始化来自Self-Supervised Learning，而Linear Transformation部分采样的是随机初始化。这两部分的参数都用Gradient Descent来更新。</p>
<blockquote>
<p>也就是说在这个例子里面，我们不必随机初始化所有的参数。,我们唯一随机初始化的部分是Linear这里。BERT的骨干是一个巨大的transformer的Encoder，这个网络的参数不是随机初始化的。把学过填空的BERT参数，放到这个地方的BERT中作为参数初始化。我们为什么要这样做呢？最直观和最简单的原因是，它比随机初始化新参数的网络表现更好。当你把学会填空的BERT放在这里时，它将获得比随机初始化BERT更好的性能。</p>
</blockquote>
<p>下图其实是个对比，就是BERT部分不用预训练模型的初始化 (scratch) 和用了预训练模型的初始化 (fine-tune) 的不同结果，不同颜色的线代表GLUE中的不同任务。 不用预训练模型的初始化会导致收敛很慢而且loss较高，说明预训练模型的初始化的作用。</p>
<p><img src="https://pluto-1300780100.cos.ap-nanjing.myqcloud.com/img/image-20221211144432325.png" alt="image-20221211144432325" style="zoom:80%;"></p>
<p><strong>Case2：词性标注：输入一个句子，输出每个词对应的词性。</strong></p>
<p>与 Case1 不一样的是，此时输入一个序列，然后输出另一个序列，而输入和输出的长度是一样的。所以输出的每个token都会做Linear Transformation+Softmax，得到类别class，就代表这个token的词性，如下图所示。</p>
<p><img src="https://pluto-1300780100.cos.ap-nanjing.myqcloud.com/img/image-20221211144518516.png" alt="image-20221211144518516"></p>
<p><strong>Case3：Natural Language Inference (NLI)：输入两个句子，输出一个类别。</strong></p>
<p>比如下图中所举的例子，其中一个句子是：A person on a horsejumps over a broken down airplane。另一个假设是：hypothesis: A person is at a diner。很明显是矛盾的，所以此时模型要输出contradiction。这个应用场景其实也是很多，比如输入一篇文章和一个留言，来让模型看看留言到底是赞成文章，还是反对文章的。把2个句子输入以后，在最前面加上1个分类符号 [CLS]，把这些拼在一起以后输入到BERT里面，当然输出也会是一个Sequence，但是我们只看 [CLS] 的输出，并把这个输出通过一个 Linear Transformation，得到分类 “赞成/反对/中性”。当然此时我们也同样需要少量的监督信息。</p>
<p><img src="https://pluto-1300780100.cos.ap-nanjing.myqcloud.com/img/image-20221211144651699.png" alt="image-20221211144651699"></p>
<p>BERT是如何解决这个问题的？你只要给它两个句子，我们在这两个句子之间放一个特殊的标记，并在最开始放CLS标记。</p>
<p><img src="https://pluto-1300780100.cos.ap-nanjing.myqcloud.com/img/image-20221211144757846.png" alt="image-20221211144757846"></p>
<p>这个序列是BERT的输入。但我们只把CLS标记作为Linear transform的输入。它决定这两个输入句子的类别。对于NLI，你必须问，这两个句子是否是矛盾的。它是用一些预先训练好的权重来初始化的。</p>
<p><strong>Case4：Extraction based Question Answering (QA)：输入一篇文章和问题，输出问题答案。</strong></p>
<p>输入是文章 D 和问题 Q ，输出是两个正整数 s 和 e 。代表index，我们把文章截取从 s 到 e 的片段之后就是问题的答案 $A={ds,…,de} $。</p>
<p><img src="https://pluto-1300780100.cos.ap-nanjing.myqcloud.com/img/image-20221211145404679.png" alt="image-20221211145404679"></p>
<p><img src="https://pluto-1300780100.cos.ap-nanjing.myqcloud.com/img/image-20221211145422793.png" alt="image-20221211145422793"></p>
<p>针对这种情况训练BERT的方法如下图所示，输入有一个question和一个document，那么它们之间要用<strong>分隔符号 [SEP]</strong> 分开。接下来我们从输出的Sequence里面挑出document对应的输出。我们除了BERT部分之外唯一需要训练的是2个vector，分别是图中橙色和蓝色的vector，这两个vector的维度和BERT的embedding dimension的维度是一致的，比如BERT的嵌入维度是768维，那这2个向量也是768维的。</p>
<p>接下来要做的是：把橙色向量和document对应的输出的每个向量做内积以后再做softmax操作，得到的最大值的索引就是document的起始位置，比如第2个0.5最大，那么这里的 s 就等于2。然后，把蓝色向量和document对应的输出的每个向量做内积以后再做softmax操作，得到的最大值的索引就是document的终止位置，比如第3个0.7最大，那么这里的 d 就等于3。再强调一遍，橙色向量和蓝色向量是随机初始化的，而BERT部分是使用Self-Supervised Learning 预训练好的。</p>
<p><img src="https://pluto-1300780100.cos.ap-nanjing.myqcloud.com/img/image-20221211145725322.png" alt="image-20221211145725322" style="zoom:80%;"></p>
<p><strong>Case5：Pre-training a seq2seq model</strong></p>
<p>下一个问题是如何让预训练的模型输出一般的句子呢？或者，如何把Pre-trained model用在这种seq2seq的model里面？</p>
<p>一种做法是如下图所示，有一个transformer，还有一个Encoder和Decoder。输入是一串句子，输出是一串句子，中间用Cross Attention连接起来，然后你故意在Encoder的输入上做一些干扰来破坏它。Encoder看到的是被破坏的结果，那么Decoder应该输出句子被破坏前的结果，训练这个模型实际上是预训练一个Seq2Seq模型。</p>
<p><img src="https://pluto-1300780100.cos.ap-nanjing.myqcloud.com/img/image-20221211150642662.png" alt="image-20221211150642662"></p>
<p>有一篇论文叫MASS，在MASS中，它说破坏的方法是，就像BERT做的那样，只要遮住一些地方就可以了，然后有各种方法来破坏它，比如，删除一些词，打乱词的顺序，旋转词的顺序。或者插入一个MASK，再去掉一些词。总之，有各种方法。在破坏了输入的句子之后，它可以通过Seq2Seq模型来恢复它。</p>
<p><img src="https://pluto-1300780100.cos.ap-nanjing.myqcloud.com/img/image-20221211150808633.png" alt="image-20221211150808633" style="zoom:80%;"></p>
<h2 id="Why-does-BERT-work"><a href="#Why-does-BERT-work" class="headerlink" title="Why does BERT work?"></a>Why does BERT work?</h2><p>最常见的解释是，当输入一串文本时，每个文本都有一个对应的向量。对于这个向量，我们称之为embedding。假设把这些字对应的向量画出来，或算它们之间的距离，你会发现意思越相近的字它们的向量越接近。那你可能会问：语言都有一字多意的问题，那应该怎么表示呢？其实 BERT 它可以考虑上下文，比如都是 “果” 这个字，上下文不同，它的向量也会不一样。比如吃苹果的 “果” 和苹果手机的 “果” 向量就不一样，如下图所示。</p>
<p><img src="https://pluto-1300780100.cos.ap-nanjing.myqcloud.com/img/image-20221211151212634.png" alt="image-20221211151212634"></p>
<p>BERT真的可以做到这件事吗？下面图30选了10个句子，前5个句子里面的 “果” 是苹果的果，后5个句子里面的 “果” 是苹果电脑的果。这10个果两两之间去计算相似度，得到一个10×10的矩阵。可以发现前五个果两两之间相似度高，后五个果两两之间相似度高，但前后的果相似度低。这说明BERT是可以根据上下文信息学到这个词的意思。著名语言大师John Rupert Firth曾说过：”You shall know a word by the company it keeps.”意思是我们是通过一个词的上下文含义来了解这个词的意思的。今天如果一个 “果” 后面跟的是树，斤这类词汇，很容易理解成苹果的果；而如果后面跟的是股价，公司这类词汇，很容易理解成苹果电脑的果。</p>
<p><img src="https://pluto-1300780100.cos.ap-nanjing.myqcloud.com/img/image-20221211151311763.png" alt="image-20221211151311763" style="zoom:80%;"></p>
<h2 id="Multi-lingual-BERT"><a href="#Multi-lingual-BERT" class="headerlink" title="Multi-lingual BERT"></a>Multi-lingual BERT</h2><p>Multi-lingual BERT是由很多语言来训练的，比如中文、英文、德文、法文等等，用填空题来训练BERT，这就是Multilingual BERT的训练方式。但是真正神奇的地方是，拿英文训练的Multi lingual BERT模型竟然能够学习到会做中文的QA问题。</p>
<p><img src="https://pluto-1300780100.cos.ap-nanjing.myqcloud.com/img/image-20221211152054701.png" alt="image-20221211152054701"></p>
<p>下图是一个真实的结果给大家参考，这边的训练的资料英文是SQuAD，中文的是DRCD。在还没有用BERT的时候是问答模型QANet的结果，它是很差的。</p>
<p>BERT我们首先在<strong>中文</strong>上做<strong>Pre-train</strong>，然后假设在<strong>中文</strong>上<strong>Fine-tune</strong>，在中文的QA问题上测试，F1 score可以达到89.1之高。</p>
<p>如果是在<strong>104种语言</strong>上做<strong>Pre-train</strong>，然后假设在<strong>中文</strong>上<strong>Fine-tune</strong>，在中文的QA问题上测试，F1 score可以达到88.7之高。</p>
<p>甚至是在<strong>104种语言</strong>上做<strong>Pre-train</strong>，然后假设在<strong>English</strong>上<strong>Fine-tune</strong>，在中文的QA问题上测试，F1 score仍可以达到78.7。注意这种情况模型<strong>从来没有看过中文的问答的资料集</strong>。仅凭在包含中文的训练集上做填空题学到的东西，它接触的唯一关于中文的东西就是填空而已。我们拿英文QA问答教它，竟然就可以自动地学会中文的QA问答。</p>
<p><img src="https://pluto-1300780100.cos.ap-nanjing.myqcloud.com/img/image-20221211152132652.png" alt="image-20221211152132652"></p>
<p><strong>为什么会这样呢？</strong>也许不同语言的词汇的Embedding是很接近的，如下图所示。也许模型在看过了大量语言以后，自动学会了这件事情。对模型来说不同语言对它都是一样的，它只看意思。但这一切的前提是你得有巨大的多语言数据集 (每种语言1000k snetences以上)才能够把模型训起来。</p>
<p><img src="https://pluto-1300780100.cos.ap-nanjing.myqcloud.com/img/image-20221211152213301.png" alt="image-20221211152213301"></p>
<p>到这里，我们知道了BERT是一个能做句子填空的模型，你给它输入一个带有Mask的英文句子，它能够填英文的空；给它输入一个带有Mask的中文句子，它能够填中文的空。但是有哪里怪怪的。BERT可以把不同语言，同样意思的符号的vector很接近，可是BERT不会把中文和英文混在一起吗？<strong>给它输入一个带有Mask的英文句子，它会填空时在空格填入中文吗？</strong></p>
<p>它没有这么做，说明它知道不同语言的信息，它并没有完全抹掉语言的资讯。下面的实验中，我们把所有英文词汇的Embedding取平均，把所有中文词汇的Embedding取平均，作差得到蓝色的向量，如图所示。</p>
<p><img src="https://pluto-1300780100.cos.ap-nanjing.myqcloud.com/img/image-20221211152324053.png" alt="image-20221211152324053"></p>
<p>得到蓝色的向量以后，给BERT输入一个英文的句子there is a cat，得到输出的黄色向量，给黄色的向量上面加上蓝色的向量，再去做填空题，就能填中文的答案了。</p>
<p><img src="https://pluto-1300780100.cos.ap-nanjing.myqcloud.com/img/image-20221211152356599.png" alt="image-20221211152356599" style="zoom:80%;"></p>
<h1 id="GPT"><a href="#GPT" class="headerlink" title="GPT"></a>GPT</h1><p>GPT要做的任务是,预测接下来,会出现的token是什么。</p>
<p>那么GPT可以把一句话补完，怎么把它用在下游任务上面呢？比如下图37，怎么把它用在翻译的任务或者其他自然语言处理的任务上呢？GPT并没有使用和BERT一样的做法：在下游任务的小数据集上做Fine-tune，可能是因为GPT的模型真的太大了，达到连Fine-tune都很有困难。望这个向量与 “台” 越接近越好。再输入 “台”，模型输出绿色的Embedding，这个Embedding经过右侧的Linear Transformation+Softmax操作得到一个向量，希望这个向量与 “湾” 越接近越好。以此类推。这就是GPT模型，它厉害的地方是用了很多训练数据训练了一个异常巨大的模型，参数量可以达到175000M=273.43爽。注意GPT的模型有点像Transformer的Decoder，也就是说输入开始符号<bos>预测 “台” 的时候模型不会看到后面的 “湾大学”，输入开始符号<bos>和”台”，预测 “湾” 的时候模型不会看到后面的 “大学”，以此类推。</bos></bos></p>
<p><img src="https://pluto-1300780100.cos.ap-nanjing.myqcloud.com/img/image-20221211153607432.png" alt="image-20221211153607432" style="zoom:80%;"></p>
<p>既然GPT有预测下一个token的能力，那它自然也就有生成文章的能力，你可以让它不断预测下一个token，产生完整的文章。最著名的是GPT曾经写了一篇和发现了独角兽 (horn) 有关的，一个活灵活现的假新闻。</p>
<p><img src="https://pluto-1300780100.cos.ap-nanjing.myqcloud.com/img/image-20221211153635497.png" alt="image-20221211153635497" style="zoom:80%;"></p>
<h1 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h1><p>本文介绍了 NLP 领域的 Self-Supervised Learning 的经典工作 BERT 和 GPT 模型，对于BERT来讲，其自监督训练的部分就是训练 BERT 做简单的填空题，这一过程需要巨大的数据集，但是令人欣慰的是这些数据集都是没有标签的资料，只是一些简单的句子，用于训练 BERT 做填空题。训练好之后的BERT具有了 Word Embedding 的能力，且这里的 Word Embedding 是可以自动地考虑上下文的，使得BERT得到的 Word Embedding 自动覆盖了上下文的信息。这样的预训练好的 BERT 模型，只需要少量的带标签数据集，就可以在无数下游任务 (Downstream Tasks) 中完成微调 (Fine-tune)，得到一个个不同的适用于下游任务的性能卓著的model。这就是 Self-Supervised Learning 的步骤和优势。</p>

                
            </div>
            <hr/>

            

    <div class="reprint" id="reprint-statement">
        
            <div class="reprint__author">
                <span class="reprint-meta" style="font-weight: bold;">
                    <i class="fas fa-user">
                        文章作者:
                    </i>
                </span>
                <span class="reprint-info">
                    <a href="/about" rel="external nofollow noreferrer">J Sir</a>
                </span>
            </div>
            <div class="reprint__type">
                <span class="reprint-meta" style="font-weight: bold;">
                    <i class="fas fa-link">
                        文章链接:
                    </i>
                </span>
                <span class="reprint-info">
                    <a href="https://jy741.gitee.io/2022/12/10/zi-jian-du-xue-xi-self-supervised-learning/">https://jy741.gitee.io/2022/12/10/zi-jian-du-xue-xi-self-supervised-learning/</a>
                </span>
            </div>
            <div class="reprint__notice">
                <span class="reprint-meta" style="font-weight: bold;">
                    <i class="fas fa-copyright">
                        版权声明:
                    </i>
                </span>
                <span class="reprint-info">
                    本博客所有文章除特別声明外，均采用
                    <a href="https://creativecommons.org/licenses/by/4.0/deed.zh" rel="external nofollow noreferrer" target="_blank">CC BY 4.0</a>
                    许可协议。转载请注明来源
                    <a href="/about" target="_blank">J Sir</a>
                    !
                </span>
            </div>
        
    </div>

    <script async defer>
      document.addEventListener("copy", function (e) {
        let toastHTML = '<span>复制成功，请遵循本文的转载规则</span><button class="btn-flat toast-action" onclick="navToReprintStatement()" style="font-size: smaller">查看</a>';
        M.toast({html: toastHTML})
      });

      function navToReprintStatement() {
        $("html, body").animate({scrollTop: $("#reprint-statement").offset().top - 80}, 800);
      }
    </script>



            <div class="tag_share" style="display: block;">
                <div class="post-meta__tag-list" style="display: inline-block;">
                    
                        <div class="article-tag">
                            
                                <a href="/tags/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/">
                                    <span class="chip bg-color">机器学习</span>
                                </a>
                            
                                <a href="/tags/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/">
                                    <span class="chip bg-color">深度学习</span>
                                </a>
                            
                        </div>
                    
                </div>
                <div class="post_share" style="zoom: 80%; width: fit-content; display: inline-block; float: right; margin: -0.15rem 0;">
                    <link rel="stylesheet" type="text/css" href="/libs/share/css/share.min.css">
<div id="article-share">

    
    <div class="social-share" data-sites="twitter,facebook,google,qq,qzone,wechat,weibo,douban,linkedin" data-wechat-qrcode-helper="<p>微信扫一扫即可分享！</p>"></div>
    <script src="/libs/share/js/social-share.min.js"></script>
    

    

</div>

                </div>
            </div>
            
                <style>
    #reward {
        margin: 40px 0;
        text-align: center;
    }

    #reward .reward-link {
        font-size: 1.4rem;
        line-height: 38px;
    }

    #reward .btn-floating:hover {
        box-shadow: 0 6px 12px rgba(0, 0, 0, 0.2), 0 5px 15px rgba(0, 0, 0, 0.2);
    }

    #rewardModal {
        width: 320px;
        height: 350px;
    }

    #rewardModal .reward-title {
        margin: 15px auto;
        padding-bottom: 5px;
    }

    #rewardModal .modal-content {
        padding: 10px;
    }

    #rewardModal .close {
        position: absolute;
        right: 15px;
        top: 15px;
        color: rgba(0, 0, 0, 0.5);
        font-size: 1.3rem;
        line-height: 20px;
        cursor: pointer;
    }

    #rewardModal .close:hover {
        color: #ef5350;
        transform: scale(1.3);
        -moz-transform:scale(1.3);
        -webkit-transform:scale(1.3);
        -o-transform:scale(1.3);
    }

    #rewardModal .reward-tabs {
        margin: 0 auto;
        width: 210px;
    }

    .reward-tabs .tabs {
        height: 38px;
        margin: 10px auto;
        padding-left: 0;
    }

    .reward-content ul {
        padding-left: 0 !important;
    }

    .reward-tabs .tabs .tab {
        height: 38px;
        line-height: 38px;
    }

    .reward-tabs .tab a {
        color: #fff;
        background-color: #ccc;
    }

    .reward-tabs .tab a:hover {
        background-color: #ccc;
        color: #fff;
    }

    .reward-tabs .wechat-tab .active {
        color: #fff !important;
        background-color: #22AB38 !important;
    }

    .reward-tabs .alipay-tab .active {
        color: #fff !important;
        background-color: #019FE8 !important;
    }

    .reward-tabs .reward-img {
        width: 210px;
        height: 210px;
    }
</style>

<div id="reward">
    <a href="#rewardModal" class="reward-link modal-trigger btn-floating btn-medium waves-effect waves-light red">赏</a>

    <!-- Modal Structure -->
    <div id="rewardModal" class="modal">
        <div class="modal-content">
            <a class="close modal-close"><i class="fas fa-times"></i></a>
            <h4 class="reward-title">你的赏识是我前进的动力</h4>
            <div class="reward-content">
                <div class="reward-tabs">
                    <ul class="tabs row">
                        <li class="tab col s6 alipay-tab waves-effect waves-light"><a href="#alipay">支付宝</a></li>
                        <li class="tab col s6 wechat-tab waves-effect waves-light"><a href="#wechat">微 信</a></li>
                    </ul>
                    <div id="alipay">
                        <img src="/medias/reward/alipay.jpg" class="reward-img" alt="支付宝打赏二维码">
                    </div>
                    <div id="wechat">
                        <img src="/medias/reward/wechat.png" class="reward-img" alt="微信打赏二维码">
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

<script>
    $(function () {
        $('.tabs').tabs();
    });
</script>

            
        </div>
    </div>

    

    

    

    

    

    

    

    

<article id="prenext-posts" class="prev-next articles">
    <div class="row article-row">
        
        <div class="article col s12 m6" data-aos="fade-up">
            <div class="article-badge left-badge text-color">
                <i class="fas fa-chevron-left"></i>&nbsp;上一篇</div>
            <div class="card">
                <a href="/2023/02/24/yi-chang-jian-ce-anomaly-detection/">
                    <div class="card-image">
                        
                        
                        <img src="/medias/featureimages/7.jpg" class="responsive-img" alt="异常检测Anomaly Detection">
                        
                        <span class="card-title">异常检测Anomaly Detection</span>
                    </div>
                </a>
                <div class="card-content article-content">
                    <div class="summary block-with-text">
                        
                            奶茶鼠的想法兔年的第一篇博客姗姗来迟咯！

                        
                    </div>
                    <div class="publish-info">
                        <span class="publish-date">
                            <i class="far fa-clock fa-fw icon-date"></i>2023-02-24
                        </span>
                        <span class="publish-author">
                            
                            <i class="fas fa-user fa-fw"></i>
                            J Sir
                            
                        </span>
                    </div>
                </div>
                
                <div class="card-action article-tags">
                    
                    <a href="/tags/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/">
                        <span class="chip bg-color">机器学习</span>
                    </a>
                    
                    <a href="/tags/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/">
                        <span class="chip bg-color">深度学习</span>
                    </a>
                    
                </div>
                
            </div>
        </div>
        
        
        <div class="article col s12 m6" data-aos="fade-up">
            <div class="article-badge right-badge text-color">
                下一篇&nbsp;<i class="fas fa-chevron-right"></i>
            </div>
            <div class="card">
                <a href="/2022/12/06/sheng-cheng-shi-dui-kang-wang-luo-gan/">
                    <div class="card-image">
                        
                        
                        <img src="/medias/featureimages/13.jpg" class="responsive-img" alt="生成式对抗网络GAN">
                        
                        <span class="card-title">生成式对抗网络GAN</span>
                    </div>
                </a>
                <div class="card-content article-content">
                    <div class="summary block-with-text">
                        
                            EverydayOneCat很多很多很多💃💃🕺🕺 

                        
                    </div>
                    <div class="publish-info">
                            <span class="publish-date">
                                <i class="far fa-clock fa-fw icon-date"></i>2022-12-06
                            </span>
                        <span class="publish-author">
                            
                            <i class="fas fa-user fa-fw"></i>
                            J Sir
                            
                        </span>
                    </div>
                </div>
                
                <div class="card-action article-tags">
                    
                    <a href="/tags/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/">
                        <span class="chip bg-color">机器学习</span>
                    </a>
                    
                    <a href="/tags/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/">
                        <span class="chip bg-color">深度学习</span>
                    </a>
                    
                </div>
                
            </div>
        </div>
        
    </div>
</article>

</div>



<!-- 代码块功能依赖 -->
<script type="text/javascript" src="/libs/codeBlock/codeBlockFuction.js"></script>

<!-- 代码语言 -->

<script type="text/javascript" src="/libs/codeBlock/codeLang.js"></script>


<!-- 代码块复制 -->

<script type="text/javascript" src="/libs/codeBlock/codeCopy.js"></script>


<!-- 代码块收缩 -->

<script type="text/javascript" src="/libs/codeBlock/codeShrink.js"></script>


    </div>
    <div id="toc-aside" class="expanded col l3 hide-on-med-and-down">
        <div class="toc-widget card" style="background-color: white;">
            <div class="toc-title"><i class="far fa-list-alt"></i>&nbsp;&nbsp;目录</div>
            <div id="toc-content"></div>
        </div>
    </div>
</div>

<!-- TOC 悬浮按钮. -->

<div id="floating-toc-btn" class="hide-on-med-and-down">
    <a class="btn-floating btn-large bg-color">
        <i class="fas fa-list-ul"></i>
    </a>
</div>


<script src="/libs/tocbot/tocbot.min.js"></script>
<script>
    $(function () {
        tocbot.init({
            tocSelector: '#toc-content',
            contentSelector: '#articleContent',
            headingsOffset: -($(window).height() * 0.4 - 45),
            collapseDepth: Number('0'),
            headingSelector: 'h1, h2, h3, h4, h5'
        });

        // modify the toc link href to support Chinese.
        let i = 0;
        let tocHeading = 'toc-heading-';
        $('#toc-content a').each(function () {
            $(this).attr('href', '#' + tocHeading + (++i));
        });

        // modify the heading title id to support Chinese.
        i = 0;
        $('#articleContent').children('h1, h2, h3, h4, h5').each(function () {
            $(this).attr('id', tocHeading + (++i));
        });

        // Set scroll toc fixed.
        let tocHeight = parseInt($(window).height() * 0.4 - 64);
        let $tocWidget = $('.toc-widget');
        $(window).scroll(function () {
            let scroll = $(window).scrollTop();
            /* add post toc fixed. */
            if (scroll > tocHeight) {
                $tocWidget.addClass('toc-fixed');
            } else {
                $tocWidget.removeClass('toc-fixed');
            }
        });

        
        /* 修复文章卡片 div 的宽度. */
        let fixPostCardWidth = function (srcId, targetId) {
            let srcDiv = $('#' + srcId);
            if (srcDiv.length === 0) {
                return;
            }

            let w = srcDiv.width();
            if (w >= 450) {
                w = w + 21;
            } else if (w >= 350 && w < 450) {
                w = w + 18;
            } else if (w >= 300 && w < 350) {
                w = w + 16;
            } else {
                w = w + 14;
            }
            $('#' + targetId).width(w);
        };

        // 切换TOC目录展开收缩的相关操作.
        const expandedClass = 'expanded';
        let $tocAside = $('#toc-aside');
        let $mainContent = $('#main-content');
        $('#floating-toc-btn .btn-floating').click(function () {
            if ($tocAside.hasClass(expandedClass)) {
                $tocAside.removeClass(expandedClass).hide();
                $mainContent.removeClass('l9');
            } else {
                $tocAside.addClass(expandedClass).show();
                $mainContent.addClass('l9');
            }
            fixPostCardWidth('artDetail', 'prenext-posts');
        });
        
    });
</script>

    

</main>


<script src="https://cdn.bootcss.com/mathjax/2.7.5/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script>
    MathJax.Hub.Config({
        tex2jax: {inlineMath: [['$', '$'], ['\(', '\)']]}
    });
</script>



    <footer class="page-footer bg-color">
    
        <link rel="stylesheet" href="/libs/aplayer/APlayer.min.css">
<style>
    .aplayer .aplayer-lrc p {
        
        display: none;
        
        font-size: 12px;
        font-weight: 700;
        line-height: 16px !important;
    }

    .aplayer .aplayer-lrc p.aplayer-lrc-current {
        
        display: none;
        
        font-size: 15px;
        color: #42b983;
    }

    
    .aplayer.aplayer-fixed.aplayer-narrow .aplayer-body {
        left: -66px !important;
    }

    .aplayer.aplayer-fixed.aplayer-narrow .aplayer-body:hover {
        left: 0px !important;
    }

    
</style>
<div class="">
    
    <div class="row">
        <meting-js class="col l8 offset-l2 m10 offset-m1 s12"
                   server="netease"
                   type="playlist"
                   id="503838841"
                   fixed='true'
                   autoplay='false'
                   theme='#42b983'
                   loop='all'
                   order='random'
                   preload='auto'
                   volume='0.7'
                   list-folded='true'
        >
        </meting-js>
    </div>
</div>

<script src="/libs/aplayer/APlayer.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/meting@2/dist/Meting.min.js"></script>

    
    <div class="container row center-align" style="margin-bottom: 0px !important;">
        <div class="col s12 m8 l8 copy-right">
            Copyright&nbsp;&copy;
            
                <span id="year">2020-2023</span>
            
            <span id="year">2020</span>
            <a href="/about" target="_blank">J Sir</a>
            |&nbsp;Powered by&nbsp;<a href="https://hexo.io/" target="_blank">Hexo</a>
            |&nbsp;Theme&nbsp;<a href="https://github.com/blinkfox/hexo-theme-matery" target="_blank">Matery</a>
            <br>
            
            &nbsp;<i class="fas fa-chart-area"></i>&nbsp;站点总字数:&nbsp;<span
                class="white-color">300.9k</span>&nbsp;字
            
            
            
            
            
            
            <span id="busuanzi_container_site_pv">
                |&nbsp;<i class="far fa-eye"></i>&nbsp;总访问量:&nbsp;<span id="busuanzi_value_site_pv"
                    class="white-color"></span>&nbsp;次
            </span>
            
            
            <span id="busuanzi_container_site_uv">
                |&nbsp;<i class="fas fa-users"></i>&nbsp;总访问人数:&nbsp;<span id="busuanzi_value_site_uv"
                    class="white-color"></span>&nbsp;人
            </span>
            
            <br>
            
            <br>
            
        </div>
        <div class="col s12 m4 l4 social-link social-statis">


    <a href="mailto:2065373132@qq.com" class="tooltipped" target="_blank" data-tooltip="邮件联系我" data-position="top" data-delay="50">
        <i class="fas fa-envelope-open"></i>
    </a>







    <a href="tencent://AddContact/?fromId=50&fromSubId=1&subcmd=all&uin=2065373132" class="tooltipped" target="_blank" data-tooltip="QQ联系我: 2065373132" data-position="top" data-delay="50">
        <i class="fab fa-qq"></i>
    </a>







    <a href="/atom.xml" class="tooltipped" target="_blank" data-tooltip="RSS 订阅" data-position="top" data-delay="50">
        <i class="fas fa-rss"></i>
    </a>

</div>
    </div>
</footer>

<div class="progress-bar"></div>


    <!-- 搜索遮罩框 -->
<div id="searchModal" class="modal">
    <div class="modal-content">
        <div class="search-header">
            <span class="title"><i class="fas fa-search"></i>&nbsp;&nbsp;搜索</span>
            <input type="search" id="searchInput" name="s" placeholder="请输入搜索的关键字"
                   class="search-input">
        </div>
        <div id="searchResult"></div>
    </div>
</div>

<script type="text/javascript">
$(function () {
    var searchFunc = function (path, search_id, content_id) {
        'use strict';
        $.ajax({
            url: path,
            dataType: "xml",
            success: function (xmlResponse) {
                // get the contents from search data
                var datas = $("entry", xmlResponse).map(function () {
                    return {
                        title: $("title", this).text(),
                        content: $("content", this).text(),
                        url: $("url", this).text()
                    };
                }).get();
                var $input = document.getElementById(search_id);
                var $resultContent = document.getElementById(content_id);
                $input.addEventListener('input', function () {
                    var str = '<ul class=\"search-result-list\">';
                    var keywords = this.value.trim().toLowerCase().split(/[\s\-]+/);
                    $resultContent.innerHTML = "";
                    if (this.value.trim().length <= 0) {
                        return;
                    }
                    // perform local searching
                    datas.forEach(function (data) {
                        var isMatch = true;
                        var data_title = data.title.trim().toLowerCase();
                        var data_content = data.content.trim().replace(/<[^>]+>/g, "").toLowerCase();
                        var data_url = data.url;
                        data_url = data_url.indexOf('/') === 0 ? data.url : '/' + data_url;
                        var index_title = -1;
                        var index_content = -1;
                        var first_occur = -1;
                        // only match artiles with not empty titles and contents
                        if (data_title !== '' && data_content !== '') {
                            keywords.forEach(function (keyword, i) {
                                index_title = data_title.indexOf(keyword);
                                index_content = data_content.indexOf(keyword);
                                if (index_title < 0 && index_content < 0) {
                                    isMatch = false;
                                } else {
                                    if (index_content < 0) {
                                        index_content = 0;
                                    }
                                    if (i === 0) {
                                        first_occur = index_content;
                                    }
                                }
                            });
                        }
                        // show search results
                        if (isMatch) {
                            str += "<li><a href='" + data_url + "' class='search-result-title'>" + data_title + "</a>";
                            var content = data.content.trim().replace(/<[^>]+>/g, "");
                            if (first_occur >= 0) {
                                // cut out 100 characters
                                var start = first_occur - 20;
                                var end = first_occur + 80;
                                if (start < 0) {
                                    start = 0;
                                }
                                if (start === 0) {
                                    end = 100;
                                }
                                if (end > content.length) {
                                    end = content.length;
                                }
                                var match_content = content.substr(start, end);
                                // highlight all keywords
                                keywords.forEach(function (keyword) {
                                    var regS = new RegExp(keyword, "gi");
                                    match_content = match_content.replace(regS, "<em class=\"search-keyword\">" + keyword + "</em>");
                                });

                                str += "<p class=\"search-result\">" + match_content + "...</p>"
                            }
                            str += "</li>";
                        }
                    });
                    str += "</ul>";
                    $resultContent.innerHTML = str;
                });
            }
        });
    };

    searchFunc('/search.xml', 'searchInput', 'searchResult');
});
</script>

    <!-- 回到顶部按钮 -->
<div id="backTop" class="top-scroll">
    <a class="btn-floating btn-large waves-effect waves-light" href="#!">
        <i class="fas fa-arrow-up"></i>
    </a>
</div>


    <script src="/libs/materialize/materialize.min.js"></script>
    <script src="/libs/masonry/masonry.pkgd.min.js"></script>
    <script src="/libs/aos/aos.js"></script>
    <script src="/libs/scrollprogress/scrollProgress.min.js"></script>
    <script src="/libs/lightGallery/js/lightgallery-all.min.js"></script>
    <script src="/js/matery.js"></script>

    <!-- Baidu Analytics -->

    <!-- Baidu Push -->

<script>
    (function () {
        var bp = document.createElement('script');
        var curProtocol = window.location.protocol.split(':')[0];
        if (curProtocol === 'https') {
            bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
        } else {
            bp.src = 'http://push.zhanzhang.baidu.com/push.js';
        }
        var s = document.getElementsByTagName("script")[0];
        s.parentNode.insertBefore(bp, s);
    })();
</script>

    
    <script src="/libs/others/clicklove.js" async="async"></script>
    
    
    <script async src="/libs/others/busuanzi.pure.mini.js"></script>
    

    

    

	
    

    

    

    
    <script src="/libs/instantpage/instantpage.js" type="module"></script>
    

<script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"pluginRootPath":"live2dw/","pluginJsPath":"lib/","pluginModelPath":"assets/","tagMode":false,"debug":false,"model":{"jsonPath":"live2d-widget-model-hibiki"},"display":{"position":"right","width":145,"height":315},"mobile":{"show":true,"scale":0.5},"react":{"opacityDefault":0.7,"opacityOnHover":0.8},"log":false});</script></body>

</html>
